# 9. diff算法原理

  1. 先同级比较,再比较子节点
  2. 先判断一方有子节点一方没子节点的状况(新增和删除子节点)
  3. 比较都有子节点的情况
  4. 递归比较子节点
function sameVnode (a, b) {
  return (
    a.key === b.key && (
      (
        a.tag === b.tag &&
        a.isComment === b.isComment &&
        isDef(a.data) === isDef(b.data) &&
        sameInputType(a, b)
      )
    )
  )
}
1
2
3
4
5
6
7
8
9
10
11
12

判断 sameNode 的时候,只会判断keytag是否有data的存在(不关心内部具体的值)是否是注释节点是否是相同的input type,来判断是否可以复用这个节点。

然后把旧的 vnode 和 新的 vnode 进行 patchVnode 操作。

在进行 patchVnode 的时候,会去检查 props 有没有变更,如果有的话去更新这个响应式的值,触发 dep.notify,触发子组件视图的重新渲染等一套很重的逻辑。 然后,还会额外的触发以下几个钩子,假设我们的组件上定义了一些dom的属性或者类名、样式、指令,那么都会被全量的更新。

updateAttrs
updateClass
updateDOMListeners
updateDOMProps
updateStyle
updateDirectives
1
2
3
4
5
6

而这些所有重量级的操作,都可以通过直接复用 相同数据的vnode 来避免,是因为我们偷懒写了 index 作为 key,而导致所有的优化失效了。
https://juejin.im/post/5e8694b75188257372503722 (opens new window)

vuediff

diff1

diff2